package com.tinem.platform.service.link.api;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.useragent.UserAgent;
import cn.hutool.http.useragent.UserAgentUtil;
import com.baidu.fsg.uid.UidGenerator;
import com.tinem.platform.client.network.IpClient;
import com.tinem.platform.module.pojo.vo.error.UserException;
import com.tinem.platform.module.pojo.vo.link.*;
import com.tinem.platform.module.pojo.vo.network.ip.IpInfoReq;
import com.tinem.platform.module.starter.jpa.entity.link.Link;
import com.tinem.platform.module.starter.jpa.entity.link.LinkEvent;
import com.tinem.platform.module.starter.jpa.repository.link.LinkEventRepository;
import com.tinem.platform.module.starter.jpa.repository.link.LinkRepository;
import com.tinem.platform.module.starter.sdk.MessageCode;
import com.tinem.platform.module.starter.web.annotation.PagingApi;
import com.tinem.platform.module.starter.web.context.GatewayContext;
import com.tinem.platform.module.starter.web.context.PageReq;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.util.Date;
import java.util.List;

/**
 * @author fengzhihao
 * @version v1
 * @program: platform
 * @className LinkApi
 * @description TODO
 * @site 
 * @company 
 * @create 2020-07-08 20:16
 */
@Slf4j
@RestController("/")
@ConfigurationProperties(prefix = "replace.link")
public class LinkApi {
    @Resource
    LinkRepository linkRepository;
    @Resource
    LinkEventRepository linkEventRepository;
    @Resource
    private UidGenerator uidGenerator;

    @Value("${open-link}")
    String openLink;
    @Resource
    IpClient ipClient;

    @Setter
    private List<String> clientIds;

    @PostMapping("add.api")
    @ResponseBody
    public AddRes add(@Valid @RequestBody AddReq addReq, HttpServletRequest request) {

        String clientId = GatewayContext.getClient();

        if(StrUtil.isBlank(addReq.getNewLink())){
            if (clientIds != null && clientIds.contains(clientId)) {
                if (StrUtil.isBlank(addReq.getNewLink())) {
                    log.info("newlink不能为空");
                    throw new UserException(MessageCode.ERROR_COMMONS_PARAMS,"newlink cannot null");
                }
            } else {
                addReq.setNewLink(openLink);
            }
        }

        Link link = new Link();
        link.setId(uidGenerator.getUID());
        link.setLinkType(addReq.getLinkType());
        link.setResourceType(addReq.getResourceType());
        link.setResourceId(addReq.getResourceId());
        link.setOldLink(addReq.getUrl());
        link.setClientId(GatewayContext.getClient());

        link.setNewLink(StrUtil.format(addReq.getNewLink(), link.getId()));

        link.setData(addReq.getData());
        link.setExpireTime(addReq.getExpireTime());
        link.setLimitTime(addReq.getLimitTime());
        link = linkRepository.saveAndFlush(link);
        AddRes addRes = new AddRes();
        addRes.setId(link.getId());
        addRes.setLinkType(link.getLinkType());
        addRes.setOldLink(link.getOldLink());
        addRes.setNewLink(link.getNewLink());
        return addRes;
    }

    @ResponseBody
    @GlobalTransactional
    @PostMapping("event.api")
    public EventRes event(@Valid @RequestBody EventReq eventReq, HttpServletRequest request) throws IOException {
        Link link = linkRepository.findById(eventReq.getId()).get();


        // 校验是否过期
        if (DateUtil.compare(link.getExpireTime(),new Date()) < 0) {
            log.info("链接已经失效");
            throw new UserException(MessageCode.ERROR_COMMONS_PARAMS,"链接已经失效");
        }

        // 校验是否超过访问次数
        if (link.getLimitTime() <= link.getVisitTime()) {
            log.info("链接超过访问次数");
            throw new UserException(MessageCode.ERROR_COMMONS_PARAMS,"链接超过访问次数");
        }

        // 增加访问次数
        link.setVisitTime(link.getVisitTime()+1);
        linkRepository.saveAndFlush(link);

        UserAgent ua = UserAgentUtil.parse(eventReq.getUa());

        LinkEvent linkEvent = new LinkEvent();
        linkEvent.setId(uidGenerator.getUID());
        linkEvent.setLinkId(link.getId());
        linkEvent.setLinkType(link.getLinkType());
        linkEvent.setClientId(GatewayContext.getClient());
        linkEvent.setResourceId(link.getResourceId());
        linkEvent.setResourceType(link.getResourceType());
        linkEvent.setReferer(eventReq.getReferer());
        linkEvent.setEventTime(new Date());
        linkEvent.setEventIp(eventReq.getIp());
        linkEvent.setEventUa(eventReq.getUa());
        linkEvent.setEventClientBrowser(ua.getBrowser().getName());
        linkEvent.setEventClientBrowserVersion(ua.getVersion());
        linkEvent.setEventClientOs(ua.getOs().getName());
        linkEvent.setEventClientPlatform(ua.getPlatform().getName());
        linkEventRepository.save(linkEvent);
        IpInfoReq ipInfoReq = new IpInfoReq();
        ipInfoReq.setIp(eventReq.getIp());
        ipClient.locat(ipInfoReq);

        return new EventRes(link.getOldLink(),linkEvent.getId(),null,
                link.getLinkType(),link.getData());
    }

    @PagingApi
    @PostMapping("eventList.api")
    @ResponseBody
    public Object eventList(@Valid @RequestBody EventListReq eventReq, HttpServletRequest request, HttpServletResponse response) throws IOException {
        return linkEventRepository.findByEventTimeBetween(eventReq.getStartTime(), eventReq.getEndTime(), PageReq.getPageRequest(request));
    }
}
